﻿using System;
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.IO;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Xml;

using FRL.DebtChased.Extensions;
using FRL.DebtChased.Repository;
using FRL.DebtChased.Types;

namespace FRL.DebtChased.WebServices
{

	/// <summary>
	/// Declaration of UserSessionTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class UserSessionTransport
	{

		[DataMember]
		public string UserDescription { get; set; }

		[DataMember]
		public int Roles { get; set; }

		[DataMember]
		public int UserId { get; set; }

		[DataMember]
		public int ClientId { get; set; }

		[DataMember]
		public int ClientContactId { get; set; }

	}

	/// <summary>
	/// Declaration of CurrencyTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class CurrencyTransport
	{

		[DataMember]
		public decimal Amount { get; set; }

		[DataMember]
		public string CurrencyCode { get; set; }

	}

	/// <summary>
	/// Declaration of CommTemplate class
	/// </summary>
	[DataContract]
	public class CommTemplateTransport
	{

		[DataMember]
		public int CommTemplateId { get; set; }

		[DataMember]
		public int CommTemplateType { get; set; }

		[DataMember]
		public string Name { get; set; }

	}

	/////////////////////////////////////////////////////////////////
	#region CommBody Editor Structures

	/// <summary>
	/// Declaration of CommBodyEditorSupportData class
	/// </summary>
	[DataContract]
	public class CommBodyEditorSupportData
	{

		[DataMember]
		public UserSessionTransport CurrentUser { get; set; }

		[DataMember]
		public List<CommTemplateTransport> Templates { get; set; }

	}

	/// <summary>
	/// Declaration of CommBodyTransport class
	/// </summary>
	[DataContract]
	public class CommBodyTransport
	{

		[DataMember]
		public int CommBodyId { get; set; }

		[DataMember]
		public int CommBodyType { get; set; }

		[DataMember]
		public string Name { get; set; }

		[DataMember]
		public List<string> SectionList { get; set; }

		[DataMember]
		public int CommTemplateId { get; set; }

		[DataMember]
		public string Subject { get; set; }

		[DataMember]
		public string Content { get; set; }

	}

	/// <summary>
	/// Declaration of CommBodySummaryTransport class
	/// </summary>
	[DataContract]
	public class CommBodySummaryTransport
	{

		[DataMember]
		public int CommBodyId { get; set; }

		[DataMember]
		public int CommBodyType { get; set; }

		[DataMember]
		public string Name { get; set; }

		[DataMember]
		public int UsageCount { get; set; }

		[DataMember]
		public List<string> SectionList { get; set; }

	}

	#endregion CommBody Editor Structures

	/// <summary>
	/// Declaration of AccountInvoiceStatusTransport class
	/// </summary>
	[DataContract]
	public class AccountInvoiceStatusTransport
	{

		[DataMember]
		public int AccountInvoiceStatusId { get; set; }

		[DataMember]
		public string InvoiceStatusName { get; set; }

		[DataMember]
		public int ClientWorkflowId { get; set; }

		[DataMember]
		public int DefaultWorkflowId { get; set; }

		[DataMember]
		public bool InUse { get; set; }

		[DataMember]
		public bool HasGlobalScope { get; set; }

		[DataMember]
		public bool IsInstalmentPlanStatus { get; set; }

		[DataMember]
		public bool IsInQuery { get; set; }

	}

	/// <summary>
	/// Declaration of WorkflowSummaryTransport class
	/// </summary>
	[DataContract]
	public class WorkflowSummaryTransport
	{

		[DataMember]
		public int WorkflowId { get; set; }

		[DataMember]
		public string WorkflowName { get; set; }

		[DataMember]
		public int InvoiceStatusId { get; set; }

		[DataMember]
		public string Summary { get; set; }

		[DataMember]
		public int UsageCount { get; set; }

		[DataMember]
		public bool IsSuperceeded { get; set; }

	}

	/// <summary>
	/// Declaration of WorkflowTransportWrapper class
	/// </summary>
	[DataContract]
	public class WorkflowTransportWrapper
	{

		[DataMember]
		public int WorkflowId { get; set; }

		[DataMember]
		public int AccountInvoiceStatusId { get; set; }

		[DataMember]
		public bool IsInstalmentPlanStatus { get; set; }

		[DataMember]
		public byte[] Buffer { get; set; }

	}

	/// <summary>
	/// Declaration of WorkflowsTransportWrapper class
	/// </summary>
	[DataContract]
	public class WorkflowsTransportWrapper
	{

		[DataMember]
		public int ClientId { get; set; }

		[DataMember]
		public string ClientName { get; set; }

		[DataMember]
		public List<AccountInvoiceStatusTransport> AccountInvoiceStatusList { get; set; }

		[DataMember]
		public List<WorkflowSummaryTransport> WorkflowList { get; set; }

	}

	/// <summary>
	/// Declaration of WorkflowSupportData class
	/// </summary>
	[DataContract]
	public class WorkflowSupportData
	{

		[DataMember]
		public UserSessionTransport CurrentUser { get; set; }

		[DataMember]
		public List<CommBodySummaryTransport> CommBodyList { get; set; }

		[DataMember]
		public Dictionary<int, string> PopupDictionary { get; set; }

		[DataMember]
		public List<string> PhoneCallReasons { get; set; }

		[DataMember]
		public List<string> PhoneCallMessages { get; set; }

		[DataMember]
		public Dictionary<int,string> LetterTypeDictionary { get; set; }

	}

	/////////////////////////////////////////////////////////////////
	#region Agent Data

	/// <summary>
	/// Declaration of AgentEditorSupportData class
	/// </summary>
	[DataContract]
	public class AgentEditorSupportData
	{

		[DataMember]
		public UserSessionTransport CurrentUser { get; set; }

		[DataMember]
		public Dictionary<string, string> CountryDictionary { get; set; }

		[DataMember]
		public List<string> ContactTitles { get; set; }

		[DataMember]
		public List<string> ContactPositions { get; set; }

		[DataMember]
		public List<string> ContactCounties { get; set; }

		[DataMember]
		public List<string> BankNames { get; set; }

	}

	/// <summary>
	/// Declaration of AgentTransport class
	/// </summary>	
	[DataContract]
	public class AgentTransport
	{

		[DataMember]
		public int AgentId { get; set; }

		[DataMember]
		public string Name { get; set; }

		[DataMember]
		public string Website { get; set; }

		[DataMember]
		public int AgentType { get; set; }

		[DataMember]
		public List<string> CoverageCountryCodes { get; set; }

		[DataMember]
		public bool UseAccountCommissionRate { get; set; }

		[DataMember]
		public string Notes { get; set; }

		[DataMember]
		public double SpecificCommissionRatePerc { get; set; }

		[DataMember]
		public List<ContactTransport> Contacts { get; set; }

		[DataMember]
		public List<BankAccountTransport> BankAccounts { get; set; }

	}

	/// <summary>
	/// Declaration of AgentSummaryTransport class
	/// </summary>
	[DataContract]
	public class AgentSummaryTransport
	{

		[DataMember]
		public int AgentId { get; set; }

		[DataMember]
		public string Name { get; set; }

		[DataMember]
		public string AgentType { get; set; }

		[DataMember]
		public string CoverageCountryCodes { get; set; }

		[DataMember]
		public string Contacts { get; set; }

	}

	#endregion Agent Data

	/////////////////////////////////////////////////////////////////
	#region Client Data

	/// <summary>
	/// Declaration of ClientEditorSupportData class
	/// </summary>
	[DataContract]
	public class ClientEditorSupportData
	{

		[DataMember]
		public UserSessionTransport CurrentUser { get; set; }

		[DataMember]
		public Dictionary<string, string> CountryMap { get; set; }

		[DataMember]
		public List<string> ContactTitles { get; set; }

		[DataMember]
		public List<string> ContactPositions { get; set; }

		[DataMember]
		public List<string> ContactCounties { get; set; }

		[DataMember]
		public List<string> ClientActivities { get; set; }

		[DataMember]
		public List<string> BankNames { get; set; }

		[DataMember]
		public Dictionary<int, string> FinanceTeamMap { get; set; }

	}

	/// <summary>
	/// Declaration of ClientTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class ClientTransport
	{

		[DataMember]
		public int ClientId { get; set; }

		[DataMember]
		public string Name { get; set; }

		[DataMember]
		public string Website { get; set; }

		[DataMember]
		public string Notes { get; set; }

		[DataMember]
		public string Activity { get; set; }

		[DataMember]
		public int InvoicingFrequency { get; set; }

		[DataMember]
		public int InvoiceTravel { get; set; }

		[DataMember]
		public int StatementFrequency { get; set; }

		[DataMember]
		public int StatementTravel { get; set; }

		[DataMember]
		public string VATNumber { get; set; }

		[DataMember]
		public string InvoicingCurrency { get; set; }

		[DataMember]
		public int ClientFundsSettings { get; set; }

		[DataMember]
		public int ClientAccountStatus { get; set; }

		[DataMember]
		public int ClientFundsFrequency { get; set; }

		[DataMember]
		public int PaymentMethod { get; set; }

		[DataMember]
		public int SalesContactId { get; set; }

		[DataMember]
		public int FinanceTeamId { get; set; }

		[DataMember]
		public int InvoiceContactId { get; set; }

		[DataMember]
		public int CommsType { get; set; }

		[DataMember]
		public int CommsFrequency { get; set; }

		[DataMember]
		public int CommsContactId { get; set; }

		[DataMember]
		public int CommsContactCCIdA { get; set; }

		[DataMember]
		public int CommsContactCCIdB { get; set; }

		[DataMember]
		public int HolidayContactId { get; set; }

		[DataMember]
		public bool IsHolidayActivated { get; set; }

		[DataMember]
		public int HolidayContactCCId { get; set; }

		[DataMember]
		public DateTime? HolidayStartAt { get; set; }

		[DataMember]
		public DateTime? HolidayEndAt { get; set; }

		[DataMember]
		public List<ClientInstructionBatchTransport> ClientInstructionBatchList { get; set; }

		[DataMember]
		public List<ContactTransport> Contacts { get; set; }

		[DataMember]
		public List<BankAccountTransport> BankAccounts { get; set; }

	}

	/// <summary>
	/// Declaration of ClientInstructionBatchTransport class
	/// </summary>
	[DataContract]
	public class ClientInstructionBatchTransport
	{

		[DataMember]
		public int ClientInstructionBatchId { get; set; }

		[DataMember]
		public string Name { get; set; }

		[DataMember]
		public bool InUse { get; set; }

	}

	/// <summary>
	/// Declaration of ClientSummaryTransport class
	/// </summary>
	[DataContract]
	public class ClientSummaryTransport
	{

		[DataMember]
		public int ClientId { get; set; }

		[DataMember]
		public string Name { get; set; }

		[DataMember]
		public string Contacts { get; set; }

	}

	#endregion Client Data

	/// <summary>
	/// Declaration of BankAccountTransport class
	/// </summary>
	[DataContract]
	public class BankAccountTransport
	{

		/////////////////////////////////////////////////////////////
		// Constants

		private const string ElementName = "BankAccountTransport";

		/////////////////////////////////////////////////////////////
		// Attributes

		[DataMember]
		public bool InUse { get; set; }

		[DataMember]
		public int BankAccountId { get; set; }

		[DataMember]
		public string CurrencyCode { get; set; }

		[DataMember]
		public string BankName { get; set; }

		[DataMember]
		public string SortCode { get; set; }

		[DataMember]
		public string AccountNo { get; set; }

		[DataMember]
		public string AccountName { get; set; }

		[DataMember]
		public string IBANNo { get; set; }

		[DataMember]
		public string SwiftCode { get; set; }

		[DataMember]
		public ContactAddressTransport Address { get; set; }

		/////////////////////////////////////////////////////////////
		// Operations

		public string GetBestName()
		{

			// Declare return variable
			string strFtmp = null;

			// Find a suitable address heading
			if (!string.IsNullOrEmpty(this.AccountNo))
				strFtmp = this.AccountNo;
			else if (!string.IsNullOrEmpty(this.AccountName))
				strFtmp = this.AccountName;
			else  if (!string.IsNullOrEmpty(this.BankName))
				strFtmp = this.BankName;
			else if (strFtmp == null)
				strFtmp = "[bank account]";

			// Add currency
			if (!string.IsNullOrEmpty(this.CurrencyCode))
			{
				Money.eCurrency Currency = Money.ParseCurrencyCode(this.CurrencyCode);
				strFtmp += string.Format(" ({0})", Money.CurrencyToSymbol(Currency));
			}

			// Return variable
			return strFtmp;

		}

		public string ToXml()
		{

			// Declare return variable
			string strFtmp = null;

			// Write to a memory stream
			using (MemoryStream ms = new MemoryStream())
			{

				// Declare a writer
				XmlWriter w = XmlWriter.Create(ms, Extensions.Extensions.GetXmlInternalWriterSettings());

				// Write the document
				w.WriteStartDocument();
				{

					// Write to xml
					w.WriteStartElement(ElementName);
					{

						// Write the attributes
						w.SafeWriteAttributeString("currencyCode", this.CurrencyCode);
						w.SafeWriteAttributeString("bankName", this.BankName);
						w.SafeWriteAttributeString("sortCode", this.SortCode);
						w.SafeWriteAttributeString("accountNo", this.AccountNo);
						w.SafeWriteAttributeString("accountName", this.AccountName);
						w.SafeWriteAttributeString("IBANNo", this.IBANNo);
						w.SafeWriteAttributeString("swiftCode", this.SwiftCode);

						// Write the elements
						this.Address.Write(w);

					}
					w.WriteEndElement();

				}
				w.WriteEndDocument();

				// Flush and close
				w.Flush();
				ms.Flush();

				// Populate a buffer
				ms.Position = 0;
				byte[] TempBuffer = ms.GetBuffer();

				// Trim the zero characters (leave one as this is unicode)
				int iLength = TempBuffer.Length;
				while (TempBuffer[iLength - 2] == 0)
					iLength--;
				byte[] NewBuffer = new byte[iLength];
				Array.Copy(TempBuffer, NewBuffer, iLength);
				strFtmp = Encoding.Unicode.GetString(NewBuffer);

			}

			// Return variable
			return strFtmp;

		}

		public string GetSearchFields()
		{

			// Build search fields
			StringBuilder sb = new StringBuilder();
			if(!string.IsNullOrEmpty(this.AccountName))
				sb.AppendFormat("{0},",this.AccountName);
			if(!string.IsNullOrEmpty(this.AccountNo))
				sb.AppendFormat("{0},", this.AccountNo);
			return sb.ToString();

		}

		public static BankAccountTransport XmlFactory(string strXml)
		{

			// Declare return variable
			BankAccountTransport Ftmp = null;

			// Convert to a buffer
			byte[] buffer = Encoding.Unicode.GetBytes(strXml);

			// Get the default XML workflow template
			using (MemoryStream ms = new MemoryStream(buffer, false))
			{

				// Open an xml reader
				XmlReader r = XmlReader.Create(ms, Extensions.Extensions.GetXmlReaderSettings());

				// Move to the start of the document
				while (!r.IsStartElement())
					r.Read();
				if (r.Name == ElementName)
				{

					// Create the workflow
					Ftmp = new BankAccountTransport();

					// Read the attributes
					Ftmp.CurrencyCode = r.GetAttribute("currencyCode");
					Ftmp.BankName = r.GetAttribute("bankName");
					Ftmp.SortCode = r.GetAttribute("sortCode");
					Ftmp.AccountNo = r.GetAttribute("accountNo");
					Ftmp.AccountName = r.GetAttribute("accountName");
					Ftmp.IBANNo = r.GetAttribute("IBANNo");
					Ftmp.SwiftCode = r.GetAttribute("swiftCode");

					// If this is an address...
					if (
						(r.Read())
						&&
						(r.NodeType == XmlNodeType.Element)
						&&
						(r.Name == ContactAddressTransport.ElementName)
					)
					{
						Ftmp.Address = new ContactAddressTransport();
						Ftmp.Address.Read(r);
					}
					else
					{
#if DEBUG
						Debug.Assert(false);
#endif // #if DEBUG
						throw new Exception("DebtChased internal error.  Cannot unwrap bank account.");
					}

				}

			}

			// Return variable
			return Ftmp;			

		}

	}

	/////////////////////////////////////////////////////////////////
	#region Contact Data

	/// <summary>
	/// Declaration of ContactTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class ContactTransport
	{

		/////////////////////////////////////////////////////////////
		// Constants

		private const string ElementName = "ContactTransport";

		/////////////////////////////////////////////////////////////
		// Attributes

		[DataMember]
		public int ContactId { get; set; }

		[DataMember]
		public bool InUse { get; set; }

		[DataMember]
		public string Title { get; set; }

		[DataMember]
		public string FirstName { get; set; }

		[DataMember]
		public string Initials { get; set; }

		[DataMember]
		public string Surname { get; set; }

		[DataMember]
		public string Abbr { get; set; }

		[DataMember]
		public string Position { get; set; }

		[DataMember]
		public DateTime? DOB { get; set; }

		[DataMember]
		public List<ContactAddressTransport> AddressList { get; set; }

		[DataMember]
		public List<ContactPointTransport> PointList { get; set; }

		[DataMember]
		public string Username { get; set; }

		[DataMember]
		public string Password { get; set; }

		[DataMember]
		public int UserRole { get; set; }

		[DataMember]
		public string Notes { get; set; }

		/////////////////////////////////////////////////////////////
		// Operations

		public string ToXml()
		{

			// Declare return variable
			string strFtmp = null;

			// Write to a memory stream
			using (MemoryStream ms = new MemoryStream())
			{

				// Declare a writer
				XmlWriter w = XmlWriter.Create(ms, Extensions.Extensions.GetXmlInternalWriterSettings());

				// Write the document
				w.WriteStartDocument();
				{

					// Write to xml
					w.WriteStartElement(ElementName);
					{

						// Write the attributes
						w.WriteAttributeBoolean("inUse", this.InUse);
						w.SafeWriteAttributeString("title", this.Title);
						w.SafeWriteAttributeString("firstName", this.FirstName);
						w.SafeWriteAttributeString("initials", this.Initials);
						w.SafeWriteAttributeString("surname", this.Surname);
						w.SafeWriteAttributeString("abbr", this.Abbr);
						w.SafeWriteAttributeString("position", this.Position);
						w.SafeWriteAttributeString("username", this.Username);
						w.SafeWriteAttributeString("password", this.Password);
						w.WriteAttributeString("userRole", ((int)this.UserRole).ToString());
						w.SafeWriteAttributeString("notes", this.Notes);

						// Write the elements
						if(this.DOB != null)
							w.SafeWriteDateTime("Dob", this.DOB.Value, false);
						foreach(ContactAddressTransport address in this.AddressList)
							address.Write(w);
						foreach(ContactPointTransport point in this.PointList)
							point.Write(w);

					}
					w.WriteEndElement();

				}
				w.WriteEndDocument();

				// Flush and close
				w.Flush();
				ms.Flush();

				// Populate a buffer
				ms.Position = 0;
				byte[] TempBuffer = ms.GetBuffer();

				// Trim the zero characters (leave one as this is unicode)
				int iLength = TempBuffer.Length;
				while (TempBuffer[iLength - 2] == 0)
					iLength--;
				byte[] NewBuffer = new byte[iLength];
				Array.Copy(TempBuffer, NewBuffer, iLength);
				strFtmp = Encoding.Unicode.GetString(NewBuffer);

			}

			// Return variable
			return strFtmp;

		}

		public string GetSearchFields()
		{

			// Build search fields
			StringBuilder sb = new StringBuilder();

			// Name
			if (!string.IsNullOrEmpty(this.FirstName))
				sb.AppendFormat("{0},", this.FirstName);
			if (!string.IsNullOrEmpty(this.Surname))
				sb.AppendFormat("{0},", this.Surname);

			// Postcodes and City
			foreach (ContactAddressTransport address in this.AddressList)
			{
				if (!string.IsNullOrEmpty(address.Postcode))
					sb.AppendFormat("{0},", address.Postcode);
				if (!string.IsNullOrEmpty(address.City))
					sb.AppendFormat("{0},", address.City);
			}

			// Point Addresses
			foreach (ContactPointTransport point in this.PointList)
			{
				if (!string.IsNullOrEmpty(point.Address))
					sb.AppendFormat("{0},", point.Address);
			}

			// Return string
			return sb.ToString();

		}

		public static ContactTransport XmlFactory(string strXml)
		{

			// Declare return variable
			ContactTransport Ftmp = null;

			// Convert to a buffer
			byte[] buffer = Encoding.Unicode.GetBytes(strXml);

			// Get the default XML workflow template
			using (MemoryStream ms = new MemoryStream(buffer, false))
			{

				// Open an xml reader
				XmlReader r = XmlReader.Create(ms, Extensions.Extensions.GetXmlReaderSettings());

				// Move to the start of the document
				while (!r.IsStartElement())
					r.Read();
				if (r.Name == ElementName)
				{

					// Create the contact object
					Ftmp = new ContactTransport();
					Ftmp.AddressList = new List<ContactAddressTransport>();
					Ftmp.PointList = new List<ContactPointTransport>();

					// Read the attributes
					Ftmp.InUse = r.SafeReadBooleanAttribute("inUse", false);
					Ftmp.Title = r.GetAttribute("title");
					Ftmp.FirstName = r.GetAttribute("firstName");
					Ftmp.Initials = r.GetAttribute("initials");
					Ftmp.Surname = r.GetAttribute("surname");
					Ftmp.Abbr = r.GetAttribute("abbr");
					Ftmp.Position = r.GetAttribute("position");
					Ftmp.Username = r.GetAttribute("username");
					Ftmp.Password = r.GetAttribute("password");
					Ftmp.UserRole = r.SafeReadIntAttribute("userRole", (int)Definitions.eRoles.NotSet);
					Ftmp.Notes = r.GetAttribute("notes");

					// If there are elements...
					if(!r.IsEmptyElement)
					{

						// Loop through elements
						while( (r.Read()) && (r.NodeType == XmlNodeType.Element) )
						{
							if (r.Name == "Dob")
								Ftmp.DOB = r.SafeReadDateTime("Dob");
							else if (r.Name == ContactPointTransport.ElementName)
							{
								ContactPointTransport newPoint = new ContactPointTransport();
								newPoint.Read(r);
								Ftmp.PointList.Add(newPoint);
							}
							else if (r.Name == ContactAddressTransport.ElementName)
							{
								ContactAddressTransport newAddress = new ContactAddressTransport();
								newAddress.Read(r);
								Ftmp.AddressList.Add(newAddress);
							}
							else
							{
#if DEBUG
								Debug.Assert(false);
#endif // #if DEBUG
								r.SkipXmlElement();
							}
						} // while-loop

					}

				}
				else
				{
#if DEBUG
					Debug.Assert(false);
#endif // #if DEBUG
					throw new Exception("DebtChased internal error.  Cannot unwrap contact.");
				}

			}

			// Return variable
			return Ftmp;

		}

		public string ComposeFullName()
		{

			// Compose string
			StringBuilder sb = new StringBuilder();
			if (!string.IsNullOrEmpty(this.FirstName))
				sb.Append(this.FirstName);
			if (!string.IsNullOrEmpty(this.Surname))
			{
				if(sb.Length > 0)
					sb.Append(" ");
				sb.Append(this.Surname);
			}
			if (
				(sb.Length == 0)
				&&
				(!string.IsNullOrEmpty(this.Abbr))
			)
				sb.Append(this.Abbr);
			if (sb.Length == 0)
				sb.Append(Definitions.Unnamed);
			return sb.ToString();

		}

	}

	/// <summary>
	/// Declaration of ContactAddressTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class ContactAddressTransport
	{

		/////////////////////////////////////////////////////////////
		// Constants

		public const string ElementName = "ContactAddressTransport";

		/////////////////////////////////////////////////////////////
		// Attributes

		[DataMember]
		public Guid ContactAddressId { get; set; }

		[DataMember]
		public int AddressType { get; set; }

		[DataMember]
		public string AddressLineA { get; set; }

		[DataMember]
		public string AddressLineB { get; set; }

		[DataMember]
		public string AddressLineC { get; set; }

		[DataMember]
		public string City { get; set; }

		[DataMember]
		public string County { get; set; }

		[DataMember]
		public string Postcode { get; set; }

		[DataMember]
		public string CountryCode { get; set; }

		/////////////////////////////////////////////////////////////
		// Operations

		public void Write(XmlWriter w)
		{

			w.WriteStartElement(ElementName);
			{

				// Get the id
				if(this.ContactAddressId == Guid.Empty)
					w.SafeWriteAttributeString("id", Guid.NewGuid().ToString());
				else
					w.SafeWriteAttributeString("id", this.ContactAddressId.ToString());

				// Write attributes
				w.WriteAttributeString("addressType", this.AddressType.ToString());
				w.SafeWriteAttributeString("lineA", this.AddressLineA);
				w.SafeWriteAttributeString("lineB", this.AddressLineB);
				w.SafeWriteAttributeString("lineC", this.AddressLineC);
				w.SafeWriteAttributeString("city", this.City);
				w.SafeWriteAttributeString("county", this.County);
				w.SafeWriteAttributeString("postcode", this.Postcode);
				w.SafeWriteAttributeString("countryCode", this.CountryCode);

			}
			w.WriteEndElement();

		}

		public void Read(XmlReader r)
		{
#if DEBUG
			Debug.Assert(r.Name == ElementName);
#endif // #if DEBUG

			// Read id
			string strId = r.GetAttribute("id");
			if (strId != null)
			{
				this.ContactAddressId = Guid.Parse(strId);
#if DEBUG
				Debug.Assert(this.ContactAddressId != Guid.Empty);
#endif // #if DEBUG
			}
			else
				this.ContactAddressId = Guid.NewGuid();

			// Read attributes
			this.AddressType = r.SafeReadIntAttribute("addressType", (int)Definitions.eContactAddressType.NotSet);
			this.AddressLineA = r.GetAttribute("lineA");
			this.AddressLineB = r.GetAttribute("lineB");
			this.AddressLineC = r.GetAttribute("lineC");
			this.City = r.GetAttribute("city");
			this.County = r.GetAttribute("county");
			this.Postcode = r.GetAttribute("postcode");
			this.CountryCode = r.GetAttribute("countryCode");

		}

	}

	/// <summary>
	/// Declaration of ContactPointTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class ContactPointTransport
	{

		/////////////////////////////////////////////////////////////
		// Constants

		public const string ElementName = "ContactPointTransport";

		/////////////////////////////////////////////////////////////
		// Attributes

		[DataMember]
		public Guid ContactPointId { get; set; }

		[DataMember]
		public int ContactPointType { get; set; }

		[DataMember]
		public int ContactPointStatus { get; set; }

		[DataMember]
		public string Address { get; set; }

		/////////////////////////////////////////////////////////////
		// Operations

		public void Write(XmlWriter w)
		{

			w.WriteStartElement(ElementName);
			{

				if(this.ContactPointId == Guid.Empty)
					w.SafeWriteAttributeString("id", Guid.NewGuid().ToString());
				else
					w.SafeWriteAttributeString("id", this.ContactPointId.ToString());

				w.WriteAttributeString("pointType", this.ContactPointType.ToString());
				w.WriteAttributeString("status", this.ContactPointStatus.ToString());
				w.SafeWriteAttributeString("address", this.Address);

			}
			w.WriteEndElement();

		}

		public void Read(XmlReader r)
		{
#if DEBUG
			Debug.Assert(r.Name == ElementName);
#endif // #if DEBUG

			// Read id
			string strId = r.GetAttribute("id");
			if (strId != null)
			{
				this.ContactPointId = Guid.Parse(strId);
#if DEBUG
				Debug.Assert(this.ContactPointId != Guid.Empty);
#endif // #if DEBUG
			}
			else
				this.ContactPointId = Guid.NewGuid();

			// Read member variables
			this.ContactPointType = r.SafeReadIntAttribute("pointType",(int)Definitions.eContactPointType.NotSet);
			this.ContactPointStatus = r.SafeReadIntAttribute("status", (int)Definitions.eContactPointStatus.NotSet);
			this.Address = r.GetAttribute("address");

		}

	}

	#endregion Contact Data

	/// <summary>
	/// Declaration of ChaseWorkspaceSupportData class
	/// </summary>
	[DataContract]
	public class ChaseWorkspaceSupportData
	{

		[DataMember]
		public UserSessionTransport CurrentUser { get; set; }

		[DataMember]
		public Dictionary<string, string> CountryMap { get; set; }

		[DataMember]
		public List<string> ContactTitles { get; set; }

		[DataMember]
		public List<string> ContactPositions { get; set; }

		[DataMember]
		public List<string> ContactCounties { get; set; }

		[DataMember]
		public List<string> BankNames { get; set; }

		[DataMember]
		public Dictionary<int, string> TradingStyleMap { get; set; }

		[DataMember]
		public Dictionary<int, string> InstalmentStatusMap { get; set; }

		[DataMember]
		public double InterestRate { get; set; }

	}

	/// <summary>
	/// Declaration of ChaseSessionItemTransport class
	/// </summary>
	[DataContract]
	public class ChaseSessionItemTransport
	{

		[DataMember]
		public int AccountId { get; set; }

		[DataMember]
		public string FRLAccountRef { get; set; }

		[DataMember]
		public string TotalAsText { get; set; }

		[DataMember]
		public List<string> ChaseReasonList { get; set; }

		[DataMember]
		public List<int> PriorityList { get; set; }

	}

	/// <summary>
	/// Declaration of AccountInvoiceTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class AccountInvoiceTransport
	{

		[DataMember]
		public int AccountInvoiceId { get; set; }

		[DataMember]
		public DateTime InvoiceDate { get; set; }

		[DataMember]
		public CurrencyTransport Amount { get; set; }

		[DataMember]
		public string InvoiceNo { get; set; }

		[DataMember]
		public int Status { get; set; }

		[DataMember]
		public bool IsInQuery { get; set; }

		[DataMember]
		public int WorkflowId { get; set; }

		[DataMember]
		public DateTime? WorkflowDay1 { get; set; }

		[DataMember]
		public bool AssociatedWithChase { get; set; }

	}

	/// <summary>
	/// Declaration of AccountNoteTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class AccountNoteTransport
	{

		/////////////////////////////////////////////////////////////
		// Attributes

		[DataMember]
		public int AccountNoteId { get; set; }

		[DataMember]
		public int UserId { get; set; }

		[DataMember]
		public string UserDescription { get; set; }

		[DataMember]
		public DateTime Timestamp { get; set; }

		[DataMember]
		public string Narrative { get; set; }

		[DataMember]
		public string Error { get; set; }

		[DataMember]
		public List<int> AccountInvoiceIds { get; set; }

		[DataMember]
		public int Flags { get; set; }

	}

	/// <summary>
	/// Declaration of AccountPrimaryClientTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class AccountPrimaryClientTransport
	{

		[DataMember]
		public int ClientId { get; set; }

		[DataMember]
		public string Name { get; set; }

		[DataMember]
		public string Website { get; set; }

		[DataMember]
		public string Notes { get; set; }

		[DataMember]
		public ContactTransport PrimaryContact { get; set; }

		[DataMember]
		public List<BankAccountTransport> BankAccounts { get; set; }

	}

	/// <summary>
	/// Declaration of AccountPlanPaymentId class
	/// </summary>
	[Serializable]
	[DataContract]
	public class AccountPlanPaymentTransport
	{

		/////////////////////////////////////////////////////////////
		// Attributes

		[DataMember]
		public int AccountPlanPaymentId { get; set; }

		[DataMember]
		public DateTime ExpectedAt { get; set; }

		[DataMember]
		public decimal Amount { get; set; }

		[DataMember]
		public string Currency { get; set; }

		[DataMember]
		public int? TransactionId { get; set; }

	}

	/// <summary>
	/// Declaration of AccountPlanTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class AccountPlanTransport
	{

		/////////////////////////////////////////////////////////////
		// Attributes

		[DataMember]
		public int AccountPlanId { get; set; }

		[DataMember]
		public int AccountId { get; set; }

		[DataMember]
		public int AccountInvoiceStatusId { get; set; }		

		[DataMember]
		public string Description { get; set; }

		[DataMember]
		public int Period { get; set; }

		[DataMember]
		public int PaymentMethod { get; set; }

		[DataMember]
		public DateTime ConfirmedAt { get; set; }

		[DataMember]
		public bool IsActive { get; set; }

		[DataMember]
		public int AccountNoteId { get; set; }

		[DataMember]
		public List<AccountPlanPaymentTransport> Payments { get; set; }

	}

	/// <summary>
	/// Declaration of AccountTransport class
	/// </summary>
	[Serializable]
	[DataContract]
	public class AccountTransport
	{

		/////////////////////////////////////////////////////////////
		// Attributes

		[DataMember]
		public int AccountId { get; set; }

		[DataMember]
		public string FRLReference { get; set; }

		[DataMember]
		public string ClientReference { get; set; }

		[DataMember]
		public string DebtorName { get; set; }

		[DataMember]
		public string DebtorClientRef { get; set; }

		[DataMember]
		public int TradingStyle { get; set; }

		[DataMember]
		public int CollectorId { get; set; }

		[DataMember]
		public int ManagerId { get; set; }

		[DataMember]
		public DateTime? ValidatedAt { get; set; }

		[DataMember]
		public int ValidatedBy { get; set; }

		[DataMember]
		public List<ContactTransport> DebtorContacts { get; set; }

		[DataMember]
		public AccountPrimaryClientTransport PrimaryClient { get; set; }

		[DataMember]
		public ContactTransport Agent { get; set; }

		[DataMember]
		public List<AccountInvoiceTransport> AccountInvoices { get; set; }

		[DataMember]
		public List<AccountNoteTransport> Notes { get; set; }
		
		[DataMember]
		public AccountPlanTransport ActiveAccountPlan { get; set; }

	}

}
